<script lang="ts" setup>
import type { IApp } from '../../../store/app'
import type { IMenu } from '../../../store/menu'
import useProjectStore from '@apps/_share/store/project'
import {
  bus,
  Tree,
} from '@pkgs/utils'
import { cloneDeep } from 'lodash-es'
import {
  EventName,
  LayoutType,
  MenuNodeType,
} from '../../../enums'
import { APP_URL_MAP } from '../../../settings'
import useAppStore from '../../../store/app'
import useConfigStore from '../../../store/config'
import useMenuStore from '../../../store/menu'
import useTabStore from '../../../store/tab'
import { isMicro } from '../../../utils'
import SubMenu from '../app-aside/sub-menu.vue'
import Breadcrumb from '../breadcrumb/index.vue'
import Fullscreen from '../fullscreen/index.vue'
import Language from '../language/index.vue'
import Timezone from '../timezone/index.vue'
import User from '../user/index.vue'

defineOptions({ name: 'AppHeader' })

const { isCollapse } = defineProps<IProps>()

const emit = defineEmits(['update:isCollapse'])

interface IProps {
  isCollapse: boolean
}

const route = useRoute()
const router = useRouter()

const projectStore = useProjectStore()
const appStore = useAppStore()
const menuStore = useMenuStore()
const tabStore = useTabStore()
const configStore = useConfigStore()

const projects = computed(() => projectStore.projects.map(({
  name,
  code,
}) => ({
  label: name,
  value: code,
})))

const showCollapse = computed(() => {
  return ![LayoutType.THREE, LayoutType.FOUR].includes(configStore.getLayoutType)
})

const customStyle = computed(() => {
  return {
    backgroundColor: configStore.getPageRegionColor.HEADER.background,
    color: configStore.getPageRegionColor.HEADER.text,
  }
})

const apps = computed<any>(() => {
  if (toValue(showCollapse)) {
    return appStore.getApps.map(({
      name,
      code,
    }) => ({
      name,
      code,
    }))
  }

  const apps = cloneDeep(appStore.getApps)
  new Tree<IApp>().traversal(apps, (app) => {
    if ((app.children || []).length > 0) {
      app.children = (app?.children ?? []).filter(({
        visible,
        type,
      }) => visible && [MenuNodeType.MENU].includes(type))
    }
  })

  return apps
})

const menus = computed(() => {
  const menus = cloneDeep(menuStore.getMenus.filter(({ visible }) => visible))
  new Tree<IMenu>().traversal(menus, (menu) => {
    if ((menu.children || []).length > 0) {
      menu.children = (menu?.children ?? []).filter(({
        visible,
        type,
      }) => visible && [MenuNodeType.MENU].includes(type))
    }
  })
  return menus
})

const defaultActive = computed(() => {
  if (toValue(showCollapse)) {
    return appStore.getAppCode
  }
  else {
    return tabStore.getCurrentTabCode
  }
})

function onChangeProject(projectCode: string) {
  projectStore.setProjectCode(projectCode)
}

function onChangeApp(code: string) {
  if (toValue(showCollapse)) {
    if (code === appStore.getAppCode)
      return

    if (isMicro(route.path)) {
      const [firstMenu] = appStore.setAppCode(code)
      tabStore.addTab(firstMenu)

      nextTick(() => {
        setTimeout(() => {
          bus.emit(EventName.SUB_ROUTE_CHANGE, {
            appCode: code,
            path: '/',
          })
        }, 1000)
      })
    }
    else {
      location.href = APP_URL_MAP[code][import.meta.env.VITE_ENV]
    }
  }
  else {
    const [, appCode] = code.split('_')
    if (appCode !== appStore.getAppCode) {
      if (isMicro(route.path)) {
        const [firstMenu] = appStore.setAppCode(appCode)
        tabStore.addTab(firstMenu)

        nextTick(() => {
          setTimeout(() => {
            bus.emit(EventName.SUB_ROUTE_CHANGE, {
              appCode,
              path: '/',
            })
          }, 1000)
        })
      }
      else {
        location.href = APP_URL_MAP[appCode][import.meta.env.VITE_ENV]
      }
      return
    }

    const menu = new Tree<IMenu>().findNode(toValue(menus), node => node.code === code) as IMenu

    if (menu.href) {
      window.open(menu.href)
    }

    else {
      tabStore.addTab(menu)
      if (!isMicro(route.path))
        router.push(menu.path)
    }
  }
}

function onChangeMenu(code: string) {
  const menu = new Tree<IMenu>().findNode(toValue(menus), node => node.code === code) as IMenu
  if (menu.href) {
    window.open(menu.href)
  }
  else {
    tabStore.addTab(menu)
    if (!isMicro(route.path))
      router.push(menu.path)
  }
}
</script>

<template>
  <div
    class="app-header"
    :style="customStyle"
  >
    <div
      flex
      items-center
      gap-8px
    >
      <button
        v-if="showCollapse"
        transition
        duration-200
        ease-in-out
        hover:scale-120
        class="i-carbon-fit-to-width text-lg"
        @click="emit('update:isCollapse', !isCollapse)"
      />

      <Fullscreen />
    </div>

    <ElDivider
      direction="vertical"
      class="border-l-#fff"
    />

    <Breadcrumb v-if="!isMicro(route.path) && showCollapse" />

    <ElMenu
      v-if="isMicro(route.path)"
      class="flex-1"
      :default-active="defaultActive"
      mode="horizontal"
      :background-color="configStore.getPageRegionColor.HEADER.background"
      :text-color="configStore.getPageRegionColor.HEADER.text"
      @select="onChangeApp"
    >
      <SubMenu
        v-for="app in apps"
        :key="app.code"
        :menu="app"
      />
    </ElMenu>

    <ElMenu
      v-if="!isMicro(route.path) && !showCollapse"
      class="flex-1"
      :default-active="defaultActive"
      mode="horizontal"
      :background-color="configStore.getPageRegionColor.HEADER.background"
      :text-color="configStore.getPageRegionColor.HEADER.text"
      @select="onChangeMenu"
    >
      <SubMenu
        v-for="menu in menus"
        :key="menu.code"
        :menu="menu"
      />
    </ElMenu>

    <div class="app-header__right">
      <ElDivider
        direction="vertical"
        class="border-l-#fff"
      />

      <BaseSelect
        v-if="projectStore.getProjectCode && isMicro(route.path)"
        class="min-w-150px"
        :clearable="false"
        :model-value="projectStore.getProjectCode"
        :options="projects"
        @change="onChangeProject"
      />

      <ElDivider
        v-if="projectStore.getProjectCode && isMicro(route.path)"
        direction="vertical"
        class="border-l-#fff"
      />

      <Language />

      <ElDivider
        direction="vertical"
        class="border-l-#fff"
      />

      <Timezone />

      <ElDivider
        direction="vertical"
        class="border-l-#fff"
      />

      <User />
    </div>
  </div>
</template>

<style lang="less" scoped>
.app-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-block: 12px;
  padding-inline: 12px;
}

.app-header__right {
  display: flex;
  align-items: center;

  column-gap: 12px;
  margin-inline-start: auto;
}

:deep(.el-menu--horizontal.el-menu) {
  border-bottom: none;
}
</style>
